In javascript null > = 0 is true while null = = 0 is false

  • 2021-07-22 08:56:30
  • OfStack

In javascript, null > = 0 is true, while null = = 0 is false

1. Preface

Today, I saw my friends discussing a question, saying whether null is equal to 0.

Hearing this, I quickly wrote an Demo and tried it 1.


<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>MR_LP:3206064928</title>
</head>
<body>

</body>
<script type="text/javascript">
  console.log(null > 0);   // false
  console.log(null < 0);   // false
  console.log(null >= 0);   // true
  console.log(null <= 0);   // true
  console.log(null == 0);   // false
  console.log(null === 0);    // false
</script>
</html>

What happened?

Why console. log (null < = 0); And console. log (null > = 0); The judgment of these two articles is true?

2. Access to information

If we want to be clear about this problem, we need to review our ECMAScript Language Specification (HTML version), which translates into ECMAScript language specification (HTML version).

2.1 Internal equality arithmetic

First of all, let's look at the algorithm implementation of internal equality operation in ES3 under 1.


11.9.3 The Abstract Equality Comparison Algorithm 
The comparison x == y, where x and y are values, produces true or false. Such a comparison is performed as follows: 
1. If Type(x) is different from Type(y), Go to step 14. 
2. If Type(x) is Undefined, return true. 
3. If Type(x) is Null, return true. 
4. If Type(x) is not Number, go to step 11. 
5. If x is NaN, return false. 
6. If y is NaN, return false. 
7. If x is the same number value as y, return true. 
8. If x is +0 and y is -0, return true. 
9. If x is -0 and y is +0, return true. 
10. Return false. 
11. If Type(x) is String, then return true if x and y are exactly the same sequence of characters (same length and same characters in corresponding positions). Otherwise, return false. 
12. If Type(x) is Boolean, return true if x and y are both true or both false. Otherwise, return false. 
13. Return true if x and y refer to the same object or if they refer to objects joined to each other (see 13.1.2). Otherwise, return false. 
14. If x is null and y is undefined, return true. 
15. If x is undefined and y is null, return true. 
16. If Type(x) is Number and Type(y) is String, return the result of the comparison x == ToNumber(y). 
17. If Type(x) is String and Type(y) is Number, return the result of the comparison ToNumber(x)== y. 
18. If Type(x) is Boolean, return the result of the comparison ToNumber(x)== y. 
19. If Type(y) is Boolean, return the result of the comparison x == ToNumber(y). 
20. If Type(x) is either String or Number and Type(y) is Object, return the result of the comparison x == ToPrimitive(y). 
21. If Type(x) is Object and Type(y) is either String or Number, return the result of the comparison ToPrimitive(x)== y. 
22. Return false.

2.2 Internal relation operation algorithm

Next, let's look at the algorithm implementation of ES3 on internal relationship operation under 1.


11.8.5 The Abstract Relational Comparison Algorithm 
The comparison x < y, where x and y are values, produces true, false, or undefined (which indicates that at least one operand is NaN). Such a comparison is performed as follows: 
1. Call ToPrimitive(x, hint Number). 
2. Call ToPrimitive(y, hint Number). 
3. If Type(Result(1)) is String and Type(Result(2)) is String, go to step 16. (Note that this step differs from step 7 in the algorithm for the addition operator **+ 
* in using *and instead of or.) 
4. Call ToNumber(Result(1)). 
5. Call ToNumber(Result(2)). 
6. If Result(4) is NaN, return undefined. 
7. If Result(5) is NaN, return undefined. 
8. If Result(4) and Result(5) are the same number value, return false. 
9. If Result(4) is +0 and Result(5) is -0, return false. 
10. If Result(4) is -0 and Result(5) is +0, return false. 
11. If Result(4) is + ∞ , return false. 
12. If Result(5) is + ∞ , return true. 
13. If Result(5) is - ∞ , return false. 
14. If Result(4) is - ∞ , return true. 
15. If the mathematical value of Result(4) is less than the mathematical value of Result(5)  -  note that these mathematical values are both finite and not both zero  -  return true. Otherwise, return false. 
16. If Result(2) is a prefix of Result(1), return false. (A string value p is a prefix of string value q if q can be the result of concatenating p and some other string*r*. Note that any string is a prefix of itself, because r may be the empty string.) 
17. If Result(1) is a prefix of Result(2), return true. 
18. Let k be the smallest nonnegative integer such that the character at position k within Result(1) is different from the character at position k within Result(2). (There must be such a k, for neither string is a prefix of the other.) 
19. Let m be the integer that is the code point value for the character at position k within Result(1). 
20. Let n be the integer that is the code point value for the character at position k within Result(2). 
21. If m < n, return true. Otherwise, return false.

2.3 Operators for ES3

2.3. 1 ES3 " > "Operator:


The Greater-than Operator ( > ) 
The production RelationalExpression : 
RelationalExpression > ShiftExpression is evaluated as follows: 
1. Evaluate RelationalExpression. 
2. Call GetValue(Result(1)). 
3. Evaluate ShiftExpression. 
4. Call GetValue(Result(3)). 
5. Perform the comparison Result(4) < Result(2). 
6. If Result(5) is undefined, return false. Otherwise, return Result(5).

2.3. 2 ES3 " > = "Operator:


The Greater-than-or-equal Operator ( >= ) 
The production RelationalExpression : 
RelationalExpression >= ShiftExpression is evaluated as follows: 
1. Evaluate RelationalExpression. 
2. Call GetValue(Result(1)). 
3. Evaluate ShiftExpression. 
4. Call GetValue(Result(3)). 
5. Perform the comparison Result(2) < Result(4). (see 11.8.5). 
6. If Result(5) is true or undefined, return false. Otherwise, return true.

2.3. 3 "==" Operator for ES3:


The Equals Operator ( == ) 
The production EqualityExpression : 
EqualityExpression == RelationalExpression is evaluated as 
follows: 
1. Evaluate EqualityExpression. 
2. Call GetValue(Result(1)). 
3. Evaluate RelationalExpression. 
4. Call GetValue(Result(3)). 
5. Perform the comparison Result(4) == Result(2). (see 11.9.3). 
6. Return Result(5).

3. Content based on information

Focus on 1, the above specially bold place, we can make clear the following 3 things.

Relational operators and equality operators are not of one category. Relational operators, in design, always require operands to try to convert to an number, while equality operators are designed without this consideration. The most important point, don't take a > b, a = = The result of b is taken for granted and a > = b to establish a connection. The correct relationship that conforms to the original design idea is a > b and a > = b is set 1. a = = b and other equality operators are set 1. For example, a = = = b, a! = b, a! = = b.

Then we can look at this problem in reverse.


null > 0   // null  Try to transform into number ,  Otherwise 0 .  So the result is  false, 
null >= 0  // null  Try to convert number , Otherwise 0 ,  The result is  true. 
null == 0  // null In terms of design, don't try to transform here .  So   The result is false. 

Here quote the big words of Franky under 1.

a > = The b operator simply goes to the a < The result of b is reversed. I think this is a design mistake. Another reason is undefined. In the standard, the sheets are carried out. Careful you must have found this point. For the design of undefined, undefined > 0 , undefined < 0, undefined = = 0, the result is designed and logical. null is the missing thing. It was not until this morning that I revisited the relevant chapters of ES 3, 5 that I suddenly realized that I didn't understand this problem fundamentally.

Although the previous example, I got catch to the original design idea of BE. But from a global perspective. From relational operators to equality operators, Especially in the design of equality operators. It's really 10 points confusing. BE mentioned in the letter, He was also frustrated with the status quo of = =. He even used the word stupid to describe his original implementation (of course, he also mentioned that it was only to design js in 10 days and run through the test cases of qa). Even so, he still said that null = = 0 was what he wanted.

Well, at this point, I also feel powerless. I think looking at the design of relational operations and equality operations in JavaScript, I can't think of any more appropriate words to describe them than confusion. This point can be proved by the large amount of type checking and defensive code in our production environment code.

At the same time, Franky also gives another example.


function case1(a){
  if(a == null){
     ....
  }
} 
 
function case2(a){
  if(a == undefined){
    ...
  }  
}
 
//  The above two groups are completely equivalent ,  This is what it is 1 Ambiguous expression .
//  We never know whether the purpose of the code writer is to match at the same time null  And  undefined Or only match one of them 1 A 
 
 
function case3(a){
  if(a === null || a === undefined){
    ...
  }
}
 
// case3  Is the best expression .  We clearly know the intention of the code writer . 
//  Even though many people may think this code is stupid .  But I firmly believe that this is good code .

Finally, I have to mention that I issued null > = 0 After this letter, Andrea Giammarchi expressed support for my previous view, and he agreed with my initial view that null > The result of = 0 should be false. It is suggested that this result be modified in the strict mode in ES7. Although it is also opposed by David Bruant. Well, for his and my misconception, observe a minute of silence …

4. Postscript

Therefore, writing code and specification should be clearly stated. Even if the expression is very wordy, it will not cause ambiguity or doubt. This is a good standard. Documents and codes. Avoiding ambiguity and various confusing rules is the most important design principle for a language.

Finally, I hope everyone can encounter fewer pits in daily development.


Related articles: